package com.webapp.org.util.aspect;

import org.apache.catalina.tribes.util.Arrays;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;

@Aspect
public class LoggingAspect
{
	// private Log log = LogFactory.getLog(this.getClass());
	private static Logger log = Logger.getLogger(LoggingAspect.class.getName());

	@Pointcut("execution(* com.webapp.org.service.*.*(..))")
	protected void loggingOperation()
	{
	}

	@Before("loggingOperation()")
	@Order(1)
	public void logJoinPoint(JoinPoint joinPoint)
	{
		System.out.println("before");
		log.info("Join point kind : " + joinPoint.getKind());
		log.info("Signature Declaing type : "
				+ joinPoint.getSignature().getDeclaringTypeName());
		log.info("Signature name : " + joinPoint.getSignature().getName());
		log.info("Arguments : " + Arrays.toString(joinPoint.getArgs()));
		log.info("Target Class : " + joinPoint.getTarget().getClass().getName());
		log.info("This Class : " + joinPoint.getThis().getClass().getName());
		log.info("Source Location : "
				+ joinPoint.getSourceLocation().toString());
	}

	@AfterReturning(pointcut = "loggingOperation()", returning = "result")
	@Order(2)
	public void logAfter(JoinPoint joinPoint, Object result)
	{
		System.out.println("Afterreturning");
		log.info("Exiting from Method :" + joinPoint.getSignature().getName());
		log.info("Return value :" + result);
	}

	@AfterThrowing(pointcut = "loggingOperation()", throwing = "e")
	@Order(3)
	public void logAfterThrowing(JoinPoint joinPoint, Throwable e)
	{
		System.out.println("throwing");
		log.error("An exception has been thrown in "
				+ joinPoint.getSignature().getName() + "()");
		log.error("Cause :" + e.getCause());
	}

	@Around("loggingOperation()")
	@Order(4)
	public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable
	{
		System.out.println("Around");
		log.info("The method " + joinPoint.getSignature().getName()
				+ "() begins with " + Arrays.toString(joinPoint.getArgs()));

		try
		{
			Object result = joinPoint.proceed();
			log.info("The method " + joinPoint.getSignature().getName()
					+ "() ends with " + result);
			return result;
		} catch (IllegalArgumentException e)
		{
			log.error("Illegal argument "
					+ Arrays.toString(joinPoint.getArgs()) + " in "
					+ joinPoint.getSignature().getName() + "()");
			throw e;
		}
	}
}
